package com.sixtyplus.semen.boardapp.board.serialport;

import android.os.Handler;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;

public class SerialPortMgr implements ISerialPortMgr {

    private final String TAG = "SerialPortMgr";
    private SerialPort mSerialPort;
    private File mSerialDevice = new File("/dev/ttyHS0");
    private FileOutputStream mOutputStream;
    private FileInputStream mInputStream;
    private ReceiveThread mReceiveThread;
    private ReceiveCallback mCallback;

    private boolean bSimulate;
    private Handler mSimulateHandler = new Handler();

    public SerialPortMgr(boolean bSimulate) {
        this.bSimulate = bSimulate;
    }

    @Override
    public boolean open(int rate, ReceiveCallback callback) {
        boolean isSuccess = false;
        mCallback = callback;
        if (bSimulate) {
            return true;
        }

        try {
            mSerialPort = new SerialPort(mSerialDevice, rate, 2);
            mOutputStream = (FileOutputStream) mSerialPort.getOutputStream();
            mInputStream = (FileInputStream) mSerialPort.getInputStream();

            mReceiveThread = new ReceiveThread();
            mReceiveThread.start();
            isSuccess = true;
            Log.e("Open serial port " + mSerialDevice, "Success!");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isSuccess;
    }

    @Override
    public boolean close() {
        boolean isSuccess = false;
        mCallback = null;
        if (bSimulate) {
            return true;
        }

        if (mReceiveThread != null) {
            mReceiveThread.close();
            mReceiveThread = null;
        }

        if (mSerialPort != null) {
            isSuccess = true;
            mSerialPort.close();
            mSerialPort = null;
        }

        return isSuccess;
    }

    @Override
    public boolean send(final byte[] data) {
        boolean isSuccess = false;
        Log.e(TAG, "Serial send: " + HexUtil.byte2HexStr(data, data.length));
        if (bSimulate) {
            mSimulateHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mCallback.onReceive(data);
                }
            }, 1000);
            return true;
        }

        try {
            mOutputStream.write(data);
            isSuccess = true;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return isSuccess;
    }

    private class ReceiveThread extends Thread {

        private boolean isRunning;

        public ReceiveThread() {
            isRunning = true;
        }

        public void close() {
            isRunning = false;
        }

        @Override
        public void run() {
            while (isRunning) {
                int size;
                try {
                    byte[] buffer = new byte[64];
                    if (mInputStream == null) {
                        return;
                    }

                    size = mInputStream.read(buffer);
                    if (size > 0) {
                        final byte[] data = Arrays.copyOf(buffer, size);
                        if (mCallback != null) {
                            mCallback.onReceive(data);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    return;
                }
            }
        }
    }
}
